package org.zjvis.datascience.web.controller.knowledgeGraph;

import com.fasterxml.jackson.databind.ObjectMapper;

import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.vo.konwledgeGraph.constructionVO.KGIndividualRequestVO;
import org.zjvis.datascience.common.vo.konwledgeGraph.constructionVO.KnowledgeGraphConstructionVO;
import org.zjvis.datascience.service.kg.KnowledgeGraphService;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;

@RequestMapping("/knowledge/graph")
@RestController
@Validated
public class KGObjectController {
    public static final Logger LOGGER = LoggerFactory.getLogger(KnowledgeGraphConstructionController.class);
    public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
    public static final Function<Long, String> NOT_FOUND_BY_ID_MESSAGE
            = knowledgeGraphFileId -> String.format("knowledgeGraphFile(id=%s) not found", knowledgeGraphFileId);
    public static final Function<String, String> NOT_FOUND_BY_PUBLISH_NO
            = publishNo -> String.format("publishNo=%s not found", publishNo);
    @Value("${restful.knowledgeGraphConstruct.url:#{null}}")
    private String KG_SERVICE_API;
    private static final OkHttpClient OK_HTTP_CLIENT = new OkHttpClient.Builder().build();
    @Autowired
    private KnowledgeGraphService knowledgeGraphService;


    @PostMapping("/individual")
    public ResponseEntity<String> saveIndividual(@Valid @RequestBody KGIndividualRequestVO requestVO
    ) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(requestVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "individual")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @PostMapping("/individual/delete")
    public ResponseEntity<String> deleteIndividual(@Valid @RequestBody KGIndividualRequestVO requestVO
    ) throws IOException {
        okhttp3.RequestBody formBody = okhttp3.RequestBody.create(MediaType.parse(org.springframework.http.MediaType.APPLICATION_JSON_VALUE), OBJECT_MAPPER.writeValueAsBytes(requestVO));
        Request request = new Request.Builder()
                .url(KG_SERVICE_API + "individual/delete")
                .post(formBody)
                .build();
        Call call = OK_HTTP_CLIENT.newCall(request);
        Response response = call.execute();
        return ResponseEntity.status(response.code()).body(response.body().string());
    }

    @GetMapping("/individuals")
    public ResponseEntity<String> getAllIndividuals(Long knowledgeGraphId, Integer pageNumber,
                                                    Integer pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            Response response = knowledgeGraphService.queryKGByGet(params, "individuals");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/by/id")
    public ResponseEntity<String> getIndividualById(Long knowledgeGraphId,
                                                    @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/by/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/by/concept/id")
    public ResponseEntity<String> getIndividualById(Long knowledgeGraphId, String conceptId,
                                                    Integer pageNumber, Integer pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("conceptId", String.valueOf(conceptId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/by/concept/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/by/concept/name")
    public ResponseEntity<String> getIndividualByConceptId(Long knowledgeGraphId, String conceptName,
                                                           Integer pageNumber, Integer pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("conceptName", String.valueOf(conceptName));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/by/concept/name");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/by/name/concept/id")
    public ResponseEntity<String> getIndividualByConceptIdAndConceptName(Long knowledgeGraphId,
                                                                         String conceptId,
                                                                         @RequestParam(name = "name") String individualName,
                                                                         Integer pageNumber, Integer pageSize) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("conceptId", String.valueOf(conceptId));
            params.put("pageNumber", String.valueOf(pageNumber));
            params.put("pageSize", String.valueOf(pageSize));
            params.put("name", String.valueOf(individualName));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/by/name/concept/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/relations/pre/id")
    public ResponseEntity<String> getAllAvailablePreRelationsById(Long knowledgeGraphId,
                                                                  @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/relations/pre/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/relations/post/id")
    public ResponseEntity<String> getAllAvailablePostRelationsById(Long knowledgeGraphId,
                                                                   @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/relations/post/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/relations/all/id")
    public ResponseEntity<String> getAllAvailableRelationsById(Long knowledgeGraphId,
                                                               @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/relations/all/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/relation-and-instance/pre/id")
    public ResponseEntity<String> getAllConnectedPreRelationCombosById(Long knowledgeGraphId,
                                                                       @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/relation-and-instance/pre/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }

    @GetMapping("/individual/relation-and-instance/all/id")
    public ResponseEntity<String> getAllConnectedRelationCombosById(Long knowledgeGraphId,
                                                                    @RequestParam(name = "id") String individualId) {
        try {
            Map<String, String> params = new ConcurrentHashMap<>();
            params.put("knowledgeGraphId", String.valueOf(knowledgeGraphId));
            params.put("id", String.valueOf(individualId));
            Response response = knowledgeGraphService.queryNebulaByGet(params, "individual/relation-and-instance/all/id");
            return ResponseEntity.status(response.code()).body(response.body().string());
        } catch (IOException ioException) {
            throw new RuntimeException(ioException.getMessage());
        }
    }
}
